'use client';

import { createRef, useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { createContext, useContext, useContextSelector } from 'use-context-selector';
import type { FC, ReactNode } from 'react';
import Loading from '@/app/components/base/loading';
import type { App } from '@/types/app';
import { Theme } from '@/types/app';
import type { ICurrentWorkspace, LangGeniusVersionResponse, UserProfileResponse } from '@/models/common';
import MaintenanceNotice from '@/app/components/header/maintenance-notice';
import type { SystemFeatures } from '@/types/feature';
import { defaultSystemFeatures } from '@/types/feature';

export type AppContextValue = {
  theme: Theme;
  setTheme: (theme: Theme) => void;
  apps: App[];
  systemFeatures?: SystemFeatures;
  mutateApps: VoidFunction;
  userProfile: UserProfileResponse;
  mutateUserProfile: VoidFunction;
  currentWorkspace: ICurrentWorkspace;
  isCurrentWorkspaceManager: boolean;
  isCurrentWorkspaceOwner: boolean;
  isCurrentWorkspaceEditor: boolean;
  isCurrentWorkspaceDatasetOperator: boolean;
  mutateCurrentWorkspace: VoidFunction;
  pageContainerRef: React.RefObject<HTMLDivElement>;
  langeniusVersionInfo: LangGeniusVersionResponse;
  useSelector: typeof useSelector;
};

const initialLangeniusVersionInfo = {
  current_env: '',
  current_version: '',
  latest_version: '',
  release_date: '',
  release_notes: '',
  version: '',
  can_auto_update: false,
};

const initialWorkspaceInfo: ICurrentWorkspace = {
  id: '',
  name: '',
  plan: '',
  status: '',
  created_at: 0,
  role: 'normal',
  providers: [],
  in_trail: true,
};

const AppContext = createContext<AppContextValue>({
  theme: Theme.light,
  systemFeatures: defaultSystemFeatures,
  setTheme: () => {},
  apps: [],
  mutateApps: () => {},
  userProfile: {
    id: '',
    name: '',
    email: '',
    avatar: '',
    is_password_set: false,
  },
  currentWorkspace: initialWorkspaceInfo,
  isCurrentWorkspaceManager: false,
  isCurrentWorkspaceOwner: false,
  isCurrentWorkspaceEditor: false,
  isCurrentWorkspaceDatasetOperator: false,
  mutateUserProfile: () => {},
  mutateCurrentWorkspace: () => {},
  pageContainerRef: createRef(),
  langeniusVersionInfo: initialLangeniusVersionInfo,
  useSelector,
});

export function useSelector<T>(selector: (value: AppContextValue) => T): T {
  return useContextSelector(AppContext, selector);
}

export type AppContextProviderProps = {
  children: ReactNode;
};

export const AppContextProvider: FC<AppContextProviderProps> = ({ children }) => {
  const pageContainerRef = useRef<HTMLDivElement>(null);

  const [userProfile] = useState<UserProfileResponse>();
  const [langeniusVersionInfo] = useState<LangGeniusVersionResponse>(initialLangeniusVersionInfo);
  const [currentWorkspace] = useState<ICurrentWorkspace>(initialWorkspaceInfo);
  const isCurrentWorkspaceManager = useMemo(
    () => ['owner', 'admin'].includes(currentWorkspace.role),
    [currentWorkspace.role],
  );
  const isCurrentWorkspaceOwner = useMemo(() => currentWorkspace.role === 'owner', [currentWorkspace.role]);
  const isCurrentWorkspaceEditor = useMemo(
    () => ['owner', 'admin', 'editor'].includes(currentWorkspace.role),
    [currentWorkspace.role],
  );
  const isCurrentWorkspaceDatasetOperator = useMemo(
    () => currentWorkspace.role === 'dataset_operator',
    [currentWorkspace.role],
  );

  const [theme, setTheme] = useState<Theme>(Theme.light);
  const handleSetTheme = useCallback((theme: Theme) => {
    setTheme(theme);
    globalThis.document.documentElement.setAttribute('data-theme', theme);
  }, []);

  useEffect(() => {
    globalThis.document.documentElement.setAttribute('data-theme', theme);
    // eslint-disable-next-line react-hooks/exhaustive-deps
  }, []);

  if (!userProfile) return <Loading type="app" />;

  return (
    <AppContext.Provider
      value={{
        theme,
        setTheme: handleSetTheme,
        apps: [],
        mutateApps: () => {},
        userProfile,
        mutateUserProfile: () => {},
        pageContainerRef,
        langeniusVersionInfo,
        useSelector,
        currentWorkspace,
        isCurrentWorkspaceManager,
        isCurrentWorkspaceOwner,
        isCurrentWorkspaceEditor,
        isCurrentWorkspaceDatasetOperator,
        mutateCurrentWorkspace: () => {},
      }}
    >
      <div className="flex flex-col h-full overflow-y-auto">
        {globalThis.document?.body?.getAttribute('data-public-maintenance-notice') && <MaintenanceNotice />}
        <div
          ref={pageContainerRef}
          className="grow relative flex flex-col overflow-y-auto overflow-x-hidden bg-background-body"
        >
          {children}
        </div>
      </div>
    </AppContext.Provider>
  );
};

export const useAppContext = () => useContext(AppContext);

export default AppContext;
